#pragma once
#include <vector>

namespace Physics
{
	class Body;
	class CollisionSkin;
	class Primitive;

	//
	// CollisionSystem
	//
	class CollisionSystem
	{
	public:
		CollisionSystem();
		virtual ~CollisionSystem();

		virtual void AddSkin(CollisionSkin* skin) = 0;
		virtual bool RemoveSkin(CollisionSkin* skin) = 0;
		virtual void CollisionSkinMoved(CollisionSkin* skin) = 0;

		virtual bool SegmentIntersect(
			float& frac, 
			CollisionSkin*& skin, 
			Vector3& pos, 
			Vector3& normal, 
			const struct Segment& seg) = 0;
		
		virtual bool SphereIntersect(
			float& frac, 
			CollisionSkin*& skin, 
			Vector3& pos, 
			Vector3& normal, 
			const struct Segment& seg,
			float radius) = 0;
	};

	//
	// CollisionSystemSAP
	//
	class CollisionSystemSAP : public CollisionSystem
	{
		typedef std::vector<CollisionSkin*> SkinVector;
		typedef std::vector<const Primitive*> PrimitiveVector;

	public:
		CollisionSystemSAP();
		virtual ~CollisionSystemSAP();

		virtual void AddSkin(CollisionSkin* skin);
		virtual bool RemoveSkin(CollisionSkin* skin);
		virtual void CollisionSkinMoved(CollisionSkin* skin) { mDirty = true; }

        void Extract(const Vector3& min, const Vector3& max, SkinVector& skins);

		virtual bool SegmentIntersect(
			float& frac, 
			CollisionSkin*& skin, 
			Vector3& pos, 
			Vector3& normal, 
			const struct Segment& seg);
		
		virtual bool SphereIntersect(
			float& frac, 
			CollisionSkin*& skin, 
			Vector3& pos, 
			Vector3& normal, 
			const struct Segment& seg,
			float radius);

	private:
		bool mDirty;
		float mLagestX;
		SkinVector mSkins;
		SkinVector mActiveSkins;
		PrimitiveVector mTestingPrims;
        PrimitiveVector mSecondPrims;
		
		void sort();
        size_t bsearch(float x);
	};
};
